#ifndef STRUCTEDGEBASE_HPP
#define STRUCTEDGEBASE_HPP

#include "edgeBase.hpp"
#include "structMeshFunctions.hpp"

namespace hms {

class StructEdgeTraits {
public:
	using VertexIndices = Array2i;
	using CellIndices   =
	#ifdef STRUCTMESH_PRECALC_EDGE_PARENT_CELLS
		Array2Xi::ConstColXpr;
	#else
		Array2i;
	#endif
};


template<typename EdgeType>
class StructEdgeBase : public EdgeBase<EdgeType>
{
public:
	using MeshType      = typename EdgeTraits<EdgeType>::MeshType;
	using CellIndices   = StructEdgeTraits::CellIndices;
	using VertexIndices = StructEdgeTraits::VertexIndices;

protected:
	const MeshType& m_mesh;
	const Index     m_index;
	const Index     m_modIndex;
	const EdgeRange m_range;

protected:
	StructEdgeBase( const MeshType&, Index );
	StructEdgeBase( const MeshType&, Index, std::pair<EdgeRange,Index> );
	
	/* these must be implemented by the specific EdgeType */
	// auto normalImp      () const -> Vector2s;
	// auto midpointImp    () const -> Vector2s;
	// auto intersectionImp() const -> Vector2s;

public:
	/**
	 * @brief The modified index is the edge's index minus the first index of
	 * its range(). So for each EdgeRange, it starts again at zero.
	 * 
	 * @return Index 
	 */
	auto modIndex      () const -> Index;
	/**
	 * @brief Returns the EdgeRange that the edge belongs to.
	 * 
	 * @return EdgeRange 
	 */
	auto range         () const -> EdgeRange;

protected:
	auto meshImp      () const -> const MeshType&;
	auto indexImp     () const -> Index;
	auto verticesImp  () const -> VertexIndices;
	auto isBoundaryImp() const -> bool;

	auto cellsImp     (Index order) const -> CellIndices;
	auto domainCellImp(Index order) const -> Index;
	auto ghostCellImp (Index order) const -> Index;
};

}

#endif